test: address PR #18 review — Phase 1.C / per-stem / dsp_utils coverage + comment + schema fixes - #19
Merged
slittycode merged 1 commit intoMay 12, 2026
Conversation
…rator, and dsp_utils Closes the test-coverage gaps flagged in the PR review. Backend: - test_analyze.py: new BandDrumDetailTests, SnareDetailTests, HihatDetailTests, TransientDensityDetailTests, SaturationDetailTests, RunPerStemAnalysesTests. Each covers null/short/silent input guards, schema-field presence, and at least one behavioral assertion against a synthetic signal that should trip the detector. RunPerStemAnalysesTests covers stems=None, empty dict, all loads failing, mono+stereo success, partial-analyzer failure, and the stereo-load-skipped path. - BassDetailTests: regression test for averageDecayMs > 30 ms on a synthetic decaying-pulse signal — guards the envelope-based fix from sliding back to the pre-fix sub-millisecond range. - test_dsp_utils.py (new): direct tests for _pearson_corr, _downsample_lufs_array, _downsample_band_energies_curve, _compute_tempo_curve_from_ticks, and _compute_stereo_correlation_curve, with closed-form expected values for perfect/anti/orthogonal correlation, constant-input NaN handling, tempo-change detection, and the silent-sub None policy. Docs / comments: - JSON_SCHEMA.md: flag bassDetail.fundamentalHz as a ZCR approximation that biases upward on harmonic-rich basses; steer Phase 2 to prefer pitchDetail when stems are available and avoid narrow filter-Q moves within ±15 Hz of the value. - phase2Validator.ts: rewrite the pathCoversTracked docstring so it matches what the code actually does (a wildcard token covers all longer citation paths under the same prefix; "stemAnalysis.*" does match "stemAnalysis.drums.spectralBalance").
slittycode
marked this pull request as ready for review
May 12, 2026 07:26
slittycode
added a commit
that referenced
this pull request
May 13, 2026
…g completion (#18) * feat: Phase 1.A–1.D depth additions, Track 2 audit, decision-gate v3 + catalog completion Substantial measurement-depth pass on the ASA Phase 1 pipeline plus a trustworthy multi-model decision-gate harness. Default Gemini model (gemini-2.5-flash) now PASSes the stem-aware gate on the Vtss bench track; Live 12 catalog completion drops UNKNOWN_PARAMETER 16 → 1 across all v3.1 snapshots. ## Depth additions (Phase 1.A – 1.D) - Phase 1.A cheap wins (5): per-frame short-term LUFS curve, per-frame 7-band spectral balance time series, instantaneous tempoCurve, per-second stereo correlationCurve, 256-point arrangement noveltyCurve (up from 64). - Phase 1.B stem-first refactor: per-stem subtree under ``stemAnalysis.{drums,bass,other,vocals}`` with the same shape as the full-mix analyzers. Phase 2 can now cite element-specific measurements. - Phase 1.C #0 real time-signature detection (onset-accent autocorrelation, replaces the always-4/4 fallback). - Phase 1.C #1 per-band transient density across the 7 spectralBalance bands (kick / hi-hat density anchors). - Phase 1.C #2 per-band stereo correlations (Utility-width-per-band recommendations). - Phase 1.C #3 ``grooveDetail.perDrumSwing.{kick,snare,hihat}`` from the mid-band beat-loudness signal. - Phase 1.C #4 snareDetail / hihatDetail band-limited drum character (hits, attack sharpness, body/snap energy ratio, decay). - Phase 1.C #5 saturationDetail (clipped sample count, peakRatio95to50, rmsToPeakRatioDb, saturationLikely). - Phase 1.C #6 32nd-note sidechain resolution + envelopeShape32 (legacy envelopeShape preserved via max-pairing downsample); pumpingRate now four-valued including thirty_second. - Phase 1.D #5 RT60 reverb per stem with perBandRt60 (low / lowMids / highMids / highs) + preDelayMs via Schroeder-equivalent slope fit. Wired through stemAnalysis.{stem}.reverbDetail. ## Track 2 audit pass 1 + measurement-quality fixes - New ``scripts/audit_pass1.py`` harness — structured 12-section markdown audit comparing real-track Phase 1 measurements against declared ground truth and sanity rules. - Bug fix: ``bassDetail.averageDecayMs`` was 0 ms on real bass material (Codex PDF finding reproduced). Root cause: decay loop searched from onset rather than peak, and checked the raw oscillating waveform rather than an envelope. Fixed with a 20 ms RMS envelope + peak-anchored search. Synthetic validation: 350 ms theoretical → 346 ms measured; 35 ms → 37 ms. Real-track Vtss: 0 ms (FAIL) → 66–125 ms (PASS). - Bug fix: ``vocalDetail.hasVocals = true`` false positive on instrumental synth content. Added temporal-formant-stability check (sustained synth leads have near-static "formants"; real vocals shift formants 100+ Hz with syllables); tightened formant tolerance 200 → 100 Hz; raised threshold 0.45 → 0.55. No-stem run on Vtss now correctly reports hasVocals=false at conf 0.48. - Pre-existing import bugs in ``analyze_segments.py``: ``_compute_stereo_metrics`` (from dsp_utils) and ``Counter`` (from collections) were undefined. ``segmentStereo`` + ``chordDetail`` now populate correctly. ## Phase 2 contract + validator + decision gate - Phase 2 prompt v3: per-stem path enumeration, citation contract (``phase1Fields`` required on every recommendation), "Phase-2 self-reference is not a citation" rule, dedicated sections for snare/hi-hat character, saturation, sidechain envelope, reverb detail. - Phase 2 schema (``server_phase2.py``): ``phase1Fields`` array required on ``mixAndMasterChain``, ``abletonRecommendations``, and ``secretSauce.workflowSteps`` items. - Frontend validator (``phase2Validator.ts``) overhaul: * 8 violation types (NUMERIC_OVERRIDE, GENRE_IGNORES_DSP, BOUNDS_VIOLATION, MISSING_CITATION, TRIVIAL_CITATIONS, NEW_FIELD_UNCITED, LOW_CONFIDENCE_NOT_HEDGED, RECOMMENDATION_SALVAGED). * Bidirectional + wildcard ``pathCoversTracked`` matcher so leaf citations satisfy parent tracked paths and ``stemAnalysis.*`` wildcards work. * 19 tracked Phase 1.A + Phase 1.C/D field paths (was 7). - Decision-gate vitests (4): single-, multi-, real-, and stem-aware multi-model comparators that read ``/tmp/decision_gate_*.json`` snapshots and emit per-model markdown reports. ## Live 12 catalog completion (UNKNOWN_PARAMETER closure) - Auto Filter: ``parameterAliases`` flat-map ``{"Filter Resonance": "Resonance", "Filter Frequency": "Frequency"}``. Closes the instrument-side long-form naming bleed. - Glue Compressor: ``allowedParameters`` expanded by 4 (Range, Sidechain, Sidechain Gain, Sidechain Dry/Wet). - ``_validate_phase2_catalog_entry`` resolves aliases before the membership check; startup-time loader validates the new ``parameterAliases`` shape. - New ``Phase2CatalogValidationTests`` (11 cases) covers alias resolution, expansion, scoping per-device, and negative cases. - New ``scripts/replay_catalog_validation.py`` — no-Gemini-spend harness that re-validates v3.1 snapshots against the live catalog. Verdict: UNKNOWN_PARAMETER drops 16 → 1 across all 8 snapshots; the remaining hit is ``EQ Eight / "Band 8 Filter Type"`` (separate device, v3.2-target). ## Test state - Backend: 374 tests pass (was 363; +11 ``Phase2CatalogValidationTests``). - Frontend: 296 tests pass (was 286; +10 validator bidirectional / wildcard tests). - UI lint clean (``tsc --noEmit``). ## Out of scope / follow-ups (documented in SESSION_BLITZ + plan) - Pro-model citation-depth iteration (3-pro and 3.1-pro still cite far less Phase 1.C/D than 2.5-flash). - gemini-3.1-pro-preview ``DROPPED_INVALID_ARRAY_ITEM`` salvage regression seen in earlier v3 runs. - Compressor "Sustain", "Ableton Project Settings", "Mixer" device hits — v3.2 prompt-fix targets. - Phase 1.D #1 madmom integration (prototype proven, install path documented at ``.runtime/reports/madmom_install_prototype_2026-05-12.md``). - Phase 1.D #2 chord progression deeper labelling. - ``JSON_SCHEMA.md`` documentation of the catalog schema (``parameterAliases`` field). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(backend): add coverage for Phase 1.C analyzers, per-stem orchestrator, and dsp_utils (#19) Closes the test-coverage gaps flagged in the PR review. Backend: - test_analyze.py: new BandDrumDetailTests, SnareDetailTests, HihatDetailTests, TransientDensityDetailTests, SaturationDetailTests, RunPerStemAnalysesTests. Each covers null/short/silent input guards, schema-field presence, and at least one behavioral assertion against a synthetic signal that should trip the detector. RunPerStemAnalysesTests covers stems=None, empty dict, all loads failing, mono+stereo success, partial-analyzer failure, and the stereo-load-skipped path. - BassDetailTests: regression test for averageDecayMs > 30 ms on a synthetic decaying-pulse signal — guards the envelope-based fix from sliding back to the pre-fix sub-millisecond range. - test_dsp_utils.py (new): direct tests for _pearson_corr, _downsample_lufs_array, _downsample_band_energies_curve, _compute_tempo_curve_from_ticks, and _compute_stereo_correlation_curve, with closed-form expected values for perfect/anti/orthogonal correlation, constant-input NaN handling, tempo-change detection, and the silent-sub None policy. Docs / comments: - JSON_SCHEMA.md: flag bassDetail.fundamentalHz as a ZCR approximation that biases upward on harmonic-rich basses; steer Phase 2 to prefer pitchDetail when stems are available and avoid narrow filter-Q moves within ±15 Hz of the value. - phase2Validator.ts: rewrite the pathCoversTracked docstring so it matches what the code actually does (a wildcard token covers all longer citation paths under the same prefix; "stemAnalysis.*" does match "stemAnalysis.drums.spectralBalance"). Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
slittycode
added a commit
that referenced
this pull request
May 31, 2026
…record (#124) * docs: refresh stale items vs current code; archive completed hosting record Sweep against the 2026-05-30 audit findings — the doc surface had drifted through the MT3, Live 12 catalogue, pianoroll/symusic, and recommendation-proof merges. Adds those features to the inventories where they were missing, fixes a wrong line reference, removes a dead commit hash, refreshes date stamps, and archives a completed-work record. - MT3 polyphonic transcription: add to apps/backend/AGENTS.md (file map + guidance), apps/backend/ARCHITECTURE.md (Components table + mt3-transcriptions route), apps/backend/README.md (Polyphonic section now reflects opt-in shipping), apps/ui/AGENTS.md + apps/ui/README.md (mt3Client.ts + UI surface), CLAUDE.md (#19 backend file, #6a frontend service), and all three CHANGELOG.md files. - Live 12 catalogue + phase2_catalogue_gates, transcription pianoroll + symusic, recommendation-proof campaign: add to CHANGELOG.md (root) and apps/backend/CHANGELOG.md and apps/ui/CHANGELOG.md. - CLAUDE.md: fix wrong analysis_runtime.py line ref (685 → ~800), add ASA_ENABLE_MT3 and ASA_SAMPLE_SYNTH_BACKEND env vars, correct the tsconfig excludes description, drop the unreachable 5c40dd4 commit hash. - apps/backend/AGENTS.md + ARCHITECTURE.md: drop the same dead 5c40dd4 hash. - docs/ARCHITECTURE_STRATEGY.md + docs/POLYPHONIC_TRANSCRIPTION_SPIKE.md: reflect that MT3 has shipped as an opt-in, additive stage (the spike harness remains the offline comparison rig for other candidates). - docs/SAMPLE_GENERATION.md: fix the schematic node label (synth_kit() → the real synth_kick/snare/hat() trio). - apps/backend/JSON_SCHEMA.md: annotate the shared-vs-full carve-out so the full-mode-only keys (keyProfile, tuningFrequency, tuningCents, lufsMomentaryMax, lufsShortTermMax, pitchDetail) are explicit per CLAUDE.md tripwire #4. - Archive docs/PUBLIC_HOSTING_FOUNDATION.md → docs/history/public-hosting-foundation-2026-04-01.md with an archived-banner; update inbound references in CHANGELOG.md, docs/SETUP.md, docs/history/README.md, and docs/history/archive/refactor-state-2026-03-18.md. - incorporations/forking-plans-2026-05-14.md: add a 2026-05-30 status update noting Plan 6 substantially landed via the Live 12 catalogue + gates work. No code touched — markdown only. https://claude.ai/code/session_016m6cUFNwb3kD2EzAbgqCHe * docs: fix self-contradictory archive banner phrasing The banner said the "Remaining work" section "lives outside this archived doc" but that section is in the doc itself. Aligns with the clearer phrasing already used in docs/history/README.md. https://claude.ai/code/session_016m6cUFNwb3kD2EzAbgqCHe --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses the blocking + should-fix + nit findings from the self-review on #18
(which GitHub rejected because you can't request changes on your own PR).
Stacks onto
feat/phase-1-depth-audit-and-gate-v3so the fixes flow into #18when this lands.
Findings addressed
Blocking — missing unit-test coverage on PR #18
BandDrumDetailTests,SnareDetailTests,HihatDetailTests,TransientDensityDetailTests,SaturationDetailTestsin
apps/backend/tests/test_analyze.py. Each covers null/short/silentinput guards, schema-field presence, and at least one behavioral
assertion against a synthetic signal that should trip the detector
(band-limited hits, mid-band onset density, hard-clipped vs dynamic
signal, etc.). Same pattern as the existing
ReverbDetailTests/BassDetailTestsclasses._run_per_stem_analyses— newRunPerStemAnalysesTestscoversstems=None, empty dict, all loads failing, two-stem success withschema shape check, "one analyzer raises for one stem, others
succeed", and the stereo-load-skipped path (LUFS/stereoDetail/truePeak
omitted but mono fields still present).
dsp_utils.py— newapps/backend/tests/test_dsp_utils.pywithdirect tests for
_pearson_corr(perfect ±1, orthogonal ≈ 0, constant→ NaN, empty → NaN, unequal-length truncation),
_downsample_lufs_array,_downsample_band_energies_curve,_compute_tempo_curve_from_ticks(steady 120 BPM resolves to 120, tempo change is reflected in curve range,
zero/negative intervals don't produce inf), and
_compute_stereo_correlation_curve(identical L/R → +1, inverted → -1,silent sub band →
None).averageDecayMs > 0regression — newtest_average_decay_ms_is_positive_for_bass_pulsesinBassDetailTests.Synthesizes eight 60 Hz pulses with a ~123 ms expected decay-to-half
and asserts
averageDecayMs ≥ 30 ms— comfortably above the pre-fixsub-ms range, while still being a positive bound that catches regression.
Should fix
pathCoversTrackeddocstring — rewrote the comment inapps/ui/src/services/phase2Validator.tsto match what the codeactually does. The old text said
stemAnalysis.*won't matchstemAnalysis.drums.spectralBalance, but the implementation'sts.length <= cs.lengthbranch runs as a wildcard-prefix scan, so itdoes match. New text walks through both examples explicitly.
Worth considering (nit)
bassDetail.fundamentalHzschema note — added an approximationwarning to
apps/backend/JSON_SCHEMA.md: ZCR/2 equals f₀ only forpure sinusoids; harmonic-rich basses bias upward; prefer
pitchDetailwhen stems are available; avoid driving a narrow filter Q within
±15 Hz without corroborating evidence.
Test results
python3.11 -m unittest tests.test_dsp_utils→ 28/28 OK (0.034 s)python3.11 -m unittest tests.test_analyze.{BandDrumDetailTests,SnareDetailTests,HihatDetailTests,TransientDensityDetailTests,SaturationDetailTests,RunPerStemAnalysesTests,BassDetailTests}→ 37/37 OK (4.168 s combined with dsp_utils above for 65/65 OK across all new + modified)npm run lint→ clean (tsc --noEmitexit 0)npm run test:unit→ 275/275 OK (vitest unit suite)Environmental errors in the broader backend suite (matplotlib / torch /
db modules) are unrelated to this change and were present pre-commit on
the same branch tip.
Test plan
BassDetailTestsregression test foraverageDecayMspassesphase2Validator.test.ts(50 tests) still passes — commentchange does not alter behavior
tsc --noEmitcleanJSON_SCHEMA.mdGenerated by Claude Code